package com.wei.miaosha.controller;

import com.google.code.kaptcha.Producer;
import com.wei.miaosha.access.AccessLimit;
import com.wei.miaosha.domain.MiaoshaUser;
import com.wei.miaosha.rabbitmq.MQSender;
import com.wei.miaosha.rabbitmq.MiaoShaMessage;
import com.wei.miaosha.redis.GoodsKey;
import com.wei.miaosha.redis.RedisService;
import com.wei.miaosha.result.CodeMsg;
import com.wei.miaosha.result.Result;
import com.wei.miaosha.service.GoodsService;
import com.wei.miaosha.service.MiaoshaService;
import com.wei.miaosha.service.MiaoshaUserService;
import com.wei.miaosha.service.OrderService;
import com.wei.miaosha.util.LogUtils;
import com.wei.miaosha.vo.GoodsVo;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;

/**
 * Created by Weizichen on 2018/8/19.
 * desc:秒杀控制层
 */
@Controller
@RequestMapping("/miaosha")
public class MiaoShaController implements InitializingBean {
    private static Logger logger = LogManager.getLogger("MiaoShaController");

    @Autowired
    RedisService redisService;

    @Autowired
    MiaoshaUserService miaoshaUserService;

    @Autowired
    GoodsService goodsService;

    @Autowired
    OrderService orderService;

    @Autowired
    MiaoshaService miaoshaService;

    @Autowired
    MQSender mqSender;

    @Autowired
    private Producer captchaProducer = null;

    private HashMap<Long, Boolean> localOverMap = new HashMap<Long, Boolean>();

    /**
     * 系统初始化前,将库存放到redis中去
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        List<GoodsVo> goodsList = goodsService.listGoodsVo();
        if (goodsList == null) {
            return;
        }
        for (GoodsVo goods : goodsList) {
            redisService.set(GoodsKey.getMiaoshaGoodscount, "" + goods.getId(), goods.getStockCount());
            localOverMap.put(goods.getId(), false);
        }

    }

    /**
     * Qps:594
     * 1000*10
     * <p>
     * 部分改redis qps:1300
     * 5000*10
     * <p>
     * 优化后全改 qps 3100
     */
    @RequestMapping(value = "/{path}/do_miaosha", method = RequestMethod.POST)
    @ResponseBody
    public Result<Integer> miaoSha(Model model, MiaoshaUser user,
                                   @RequestParam("goodsId") long goodsId,
                                   @PathVariable("path") String path) {
        if (user == null) {
            return Result.error(CodeMsg.SESSION_ERROR);
        }
        //验证path
        boolean check = miaoshaService.checkPath(user, goodsId, path);
        if (!check) {
            return Result.error(CodeMsg.REQUEST_ILLEGAL);
        }
        //内存标记减少开销
        Boolean flag = localOverMap.get(goodsId);
        if (flag) {
            //库存没有
            return Result.error(CodeMsg.MIAO_SHA_OVER);
        }

        //先从redis中预减库存
        long stock = redisService.decr(GoodsKey.getMiaoshaGoodscount, "" + goodsId);
        if (stock < 0) {
            localOverMap.put(goodsId, true);
            return Result.error(CodeMsg.MIAO_SHA_OVER);
        }
        GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
        //减库存生成秒杀订单
        // OrderInfo orderInfo = miaoshaService.miaoSha(user, goods);
        MiaoShaMessage mm = new MiaoShaMessage();
        mm.setUser(user);
        mm.setGoodsId(goodsId);
        //进入队列
        mqSender.send(mm);
        return Result.success(0);//0为排队中
    /* GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
        long stockCount = goods.getStockCount();
        //库存数
        if (stockCount <= 0) {
            //库存不足
            return Result.error(CodeMsg.MIAO_SHA_OVER);
        }
        //判断是否是秒杀到,这里改到redis查询
        MiaoshaOrder order = orderService.getMiaoshaOrderByGoodsId(user.getId(), goodsId);
        if (order != null) {
            //已经是秒杀到
            return Result.error(CodeMsg.REPEATE_MIAOSHA);
        }
        //减库存 下订单 写入秒杀订单
        OrderInfo orderInfo = miaoshaService.miaoSha(user, goods);
        return Result.success(orderInfo);*/
    }

    /**
     * @param model
     * @param user
     * @param goodsId
     * @return -1 商品不足,goodsId 商品id,0 排队中
     */
    @AccessLimit(seconds = 5, maxCount = 10, needLogin = true)
    @RequestMapping(value = "/result", method = RequestMethod.GET)
    @ResponseBody
    public Result<Long> miaoShaResult(Model model, MiaoshaUser user,
                                      @RequestParam("goodsId") long goodsId) {
        if (user == null) {
            return Result.error(CodeMsg.SESSION_ERROR);
        }
        long result = miaoshaService.getMiaoShaResult(user.getId(), goodsId);
        return Result.success(result);
    }


    /**
     * 获取秒杀的path
     *
     * @param model
     * @param user
     * @param goodsId
     * @return 地址字符串
     */
    @AccessLimit(seconds = 5, maxCount = 5, needLogin = true)
    @RequestMapping(value = "/path", method = RequestMethod.GET)
    @ResponseBody
    public Result<String> getMiaoShaPath(HttpServletRequest request, Model model, MiaoshaUser user,
                                         @RequestParam("goodsId") long goodsId,
                                         @RequestParam(value = "verifyCode") String verifyCode) {

        if (user == null) {
            return Result.error(CodeMsg.SESSION_ERROR);
        }
        boolean check = miaoshaService.checkVerifyCode(user, goodsId, verifyCode);
        if (!check) {
            return Result.error(CodeMsg.REQUEST_ILLEGAL);
        }
        String path = miaoshaService.createMiaoShaPath(user, goodsId);
        LogUtils.infoLog(logger, " " + "-" + " " + "-" + " " + "success" + " " + "获取秒杀路径");
        return Result.success(path);
    }

    /**
     * 生成验证码图片,运算验证
     *
     * @param response
     * @param user
     * @param goodsId
     * @return 地址字符串
     */
    @RequestMapping(value = "/verifyCode", method = RequestMethod.GET)
    @ResponseBody
    public Result<String> getVerifyCode(HttpServletResponse response, MiaoshaUser user,
                                        @RequestParam("goodsId") long goodsId) {
        if (user == null) {
            return Result.error(CodeMsg.SESSION_ERROR);
        }
        BufferedImage image = miaoshaService.createVerifyCode(user, goodsId);
        try {
            ServletOutputStream outputStream = response.getOutputStream();
            ImageIO.write(image, "JPEG", outputStream);
            outputStream.flush();
            outputStream.close();
            LogUtils.infoLog(logger, " " + "-" + " " + "-" + " " + "success" + " " + "生成运算验证码");
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            LogUtils.infoLog(logger, "-" + " " + "-" + " " + "-" + " " + "fail" + " " + "生成运算验证码");
            return Result.error(CodeMsg.MIAO_SHA_FAILED);
        }

    }

    /**
     * 生成验证码图片,简单4个字母或者数字比对
     *
     * @param response
     * @param user
     * @param goodsId
     * @return 地址字符串
     */
    @RequestMapping("/kaptcha")
    @ResponseBody
    public Result<String> getKaptchaImage(HttpServletRequest request, @RequestParam("goodsId") long goodsId,
                                          MiaoshaUser user, HttpServletResponse response) {
        //HttpSession session = request.getSession();
        response.setDateHeader("Expires", 0);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");
        response.setContentType("image/jpeg");
        //生成验证码
        String capText = captchaProducer.createText();
        miaoshaService.saveVerifyCode(user, goodsId, capText);
        //session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
        //向客户端写出
        BufferedImage bi = captchaProducer.createImage(capText);
        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
            ImageIO.write(bi, "jpg", out);
            out.flush();
            out.close();
            LogUtils.infoLog(logger, " " + "-" + " " + "-" + " " + "success" + " " + "生成验证码");
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return Result.error(CodeMsg.MIAO_SHA_FAILED);
        }
    }
}